package particleField;

import java.awt.Stroke;
import java.awt.print.Paper;
import java.util.ArrayList;

import javax.media.opengl.GL;
import javax.sound.sampled.Line;


import processing.core.*;
import processing.opengl.PGraphicsOpenGL;

public class ParticleSystem {

	ArrayList<Particle> particles; // An arraylist for all the particles
	PVector origin; // An origin point for where particles are born
	PVector[][] magneticField;
	float a;
	private int numberOfThreads = 4;
	private int numberOfParticles; //per Thread

	public ParticleSystem(int num, PVector v, PApplet pa) {
		particles = new ArrayList(); // Initialize the arraylist
		origin = v.get(); // Store the origin point
		magneticField = new PVector[(int)v.x][(int)v.y];
		
		resetMagField();
		

		
		for (int x = 10; x < v.x; x+= 10) {
			for (int y = 10; y < v.y; y+=10) {
				addParticle(x, y);

			}			
		}
		System.out.println("Anzahl Partikel: " + particles.size());
		numberOfParticles = particles.size()/numberOfThreads;
		System.out.println("Partikel pro Thread: "+numberOfParticles);
		for(int i=0; i<numberOfThreads; i++){
			Thread t = new Thread(new ParticleUpdate(pa, particles.subList(i*numberOfParticles, (i+1)*numberOfParticles)));
			t.start();
		}
	}

	public void resetMagField() {
		for (int i = 0; i < magneticField.length; i++) {
			for (int j = 0; j < magneticField[0].length; j++) {
//				float t1 = (float)( ((i*1.0)/(float)magneticField.length)*2*Math.PI);
//				float t2 = (float)((j*1.0/(float)magneticField[0].length)*2*Math.PI);
				magneticField[i][j] = new PVector();
			}			
		}
	}

	public void run(PApplet pa) {
		// Cycle through the ArrayList backwards b/c we are deleting
		
		PGraphicsOpenGL glb = (PGraphicsOpenGL) pa.g;
		GL gl = glb.beginGL();
		


		
		for (int i = particles.size() - 1; i >= 0; i--) {
			Particle p = (Particle) particles.get(i);
			
			gl.glColor3f( 1, 1, 1);
//			gl.glRectf(p.loc.x, p.loc.y, p.loc.x+2, p.loc.y+2);
			gl.glRectf(p.loc.x, p.loc.y, p.loc.x+p.velo_height, p.loc.y+p.velo_height);
		}

		glb.endGL();
		
//		System.out.println(particles.size());
		
//		showDirection(pa);
		
	}

	public void force_home() {
		for (Particle elem : particles) {
			elem.force_home();
		}
	}

	public void force_disable_home() {
		for (Particle elem : particles) {
			elem.force_disable_home();
		}
	}
	
	public void add_magnet(PApplet pa, PVector mag, int radius, boolean magnetic){
		mag = new PVector(mag.x, mag.y);
		
		int beg_y = 0;
		int beg_x = 0;
		
//		if(mag.y - radius >= 0 && mag.x - radius >= 0 ){
//			beg_y = (int) (mag.y - radius);
//			beg_x = (int) (mag.x - radius);
//		}
		
		
		for (int i = beg_x; i < magneticField.length /*&& i < (beg_x+2*radius)*/; i++) {
			for (int j = beg_y; j < magneticField[0].length  /*&& j < (beg_y+2*radius)*/; j++) {
//				pa.ellipse(i, j, 1, 1);
				float dist = mag.dist( new PVector(i, j));
				if( dist < radius){
					PVector tmp = PVector.sub( new PVector(i, j), mag);
					tmp.mult((float) (((1-dist/radius))*0.2) );
					if(magnetic) tmp.mult(-1);
					magneticField[i][j].set(tmp);
					magneticField[i][j].normalize();
					magneticField[i][j].mult(0.5f);

				}
			}			
		}
		
	}
	
	public void add_magneticBox(PApplet pa, int radius){
		//linker streifen
		for (int i = 0; i < magneticField.length; i++) {
			for (int j = 0; j < radius; j++) {
//				pa.ellipse(j, i, 1, 1);
				PVector tmp = PVector.sub( new PVector(i, j), new PVector(magneticField[0].length/2, magneticField.length/2));
				magneticField[i][j].set(tmp);
				magneticField[i][j].normalize();
				magneticField[i][j].mult(-2.1f);
			}
		}
		
		//rechter streifen
		for (int i = 0; i < magneticField.length; i++) {
			for (int j = magneticField[0].length-radius; j < magneticField[0].length; j++) {
//				pa.ellipse(j, i, 1, 1);
				PVector tmp = PVector.sub( new PVector(i, j), new PVector(magneticField[0].length/2, magneticField.length/2));
				magneticField[i][j].set(tmp);
				magneticField[i][j].normalize();
				magneticField[i][j].mult(-2.1f);
			}
		}
//		
//		//unterer streifen
	for (int i = radius; i < magneticField[0].length-radius; i++) {
		for (int j = magneticField.length-radius; j < magneticField.length; j++) {
//			pa.ellipse(i, j, 1, 1);
			PVector tmp = PVector.sub( new PVector(j, i), new PVector(magneticField[0].length/2, magneticField.length/2));
			magneticField[j][i].set(tmp);
			magneticField[j][i].normalize();
			magneticField[j][i].mult(-2.1f);
		}
	}
//		//oberer streifen
		for (int i = radius; i < magneticField[0].length-radius; i++) {
			for (int j = 0; j < radius; j++) {
//				pa.ellipse(i, j, 1, 1);
				PVector tmp = PVector.sub( new PVector(j, i), new PVector(magneticField[0].length/2, magneticField.length/2));
				magneticField[j][i].set(tmp);
				magneticField[j][i].normalize();
				magneticField[j][i].mult(-2.1f);
			}
		}
		
	}

	public  void showDirection(PApplet pa) {
		pa.stroke(0);
		for (int i = 10; i < magneticField.length; i+=2) {
			for (int j = 10; j < magneticField[0].length; j+=2) {
				pa.fill( pa.color(0,0,0) );
				pa.stroke(0);
//				System.out.println("x-anteil: " + magneticField[i][j].y + "y-anteil" + magneticField[i][j].x);
				pa.line(j, i, j+magneticField[i][j].y*1.1f, i+magneticField[i][j].x*1.1f);
//				pa.rect(i, j, 1, 1);
			}			
		}
	}
	
	
	public void addForceDirection(PVector a, double angle){

		a = new PVector(a.x, a.y);
		int radius = 50;

		for (Particle elem : particles) {
			float dist = a.dist( elem.loc);
			if( dist < radius){
//				PVector tmp = PVector.sub(elem.loc, a);
				PVector tmp = new PVector(getx_Polar(1, angle), gety_Polar(1, angle));
				tmp.normalize();
				tmp.mult( 1-(float)((dist/radius)) );
				tmp.mult(2f);
				elem.vel.add(tmp);
			}
			
		}
	}
	
	public void addForceDirection(PVector a, PVector b){
		for (Particle elem : particles) {
			PVector tmp = PVector.sub(elem.loc, a);
			tmp.normalize();
//			tmp.mult( 1-(float)((dist/radius)) );
			elem.vel.add(tmp);
		}
		
	}
	
	public void addForceDirection(PVector a){

		a = new PVector(a.x, a.y);
		int radius = 50;

		for (Particle elem : particles) {
			float dist = a.dist( elem.loc);
			if( dist < radius){
				PVector tmp = PVector.sub(elem.loc, a);
				tmp.normalize();
				tmp.mult( 1-(float)((dist/radius)) );
				tmp.mult(2f);
				elem.vel.add(tmp);
			}
			
		}
	}
	
	public void gravity() {
		for (Particle elem : particles) {
			elem.vel.add(0, 1, 0);		
		}
	}
	
	private boolean isInRange(int x, int beg, int end){
		if( x >= 0 && x < end){
			return true;
		}else{
			return false;
		}
	}

	void addParticle() {
//			particles.add(new Particle(origin));
	  }

	private void addParticle(float x, float y) {		
			particles.add(new Particle(new PVector(x, y), magneticField));
	}

	void addParticle(Particle p) {
		particles.add(p);
	}

	// A method to test if the particle system still has particles
	boolean dead() {
		if (particles.isEmpty()) {
			return true;
		} else {
			return false;
		}
	}
	
	private int getx_Polar(double radius, double angle){
		return (int) (radius*(Math.cos(angle/360*2*Math.PI)) );
	}
	
	private int gety_Polar(double radius, double angle){
		return (int) (radius*(Math.sin(angle/360*2*Math.PI)) );
	}
	
	public void loadDirectionPic(PApplet pa){
		PImage img = pa.loadImage("TestForm2.png");
		
		for (int i = 0;  i < img.width; i+= 1) {
			for (int j = 0; j < img.height; j+= 1) {
				
				int gray = img.get(i, j);
				if(gray != 0xFFFFFFFF ){
					magneticField[i][j] = new PVector( (float)Math.cos( (gray&0xFF)*10), (float)Math.sin( (gray&0xFF)*10) );
				}
				
				
			}
		}
		

	}
}